/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2007, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.vm; import java.io.File; import java.lang.management.ManagementFactory; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; /** * <p>Title: VirtualMachineBootstrap</p> * <p>Description: Bootstraps the Java Attach API class set</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * @version $LastChangedRevision$ * <p><code>org.helios.vm.VirtualMachineBootstrap</code></p> */ public class VirtualMachineBootstrap { /** The singleton instance */ protected static volatile VirtualMachineBootstrap instance = null; /** The singleton instance ctor lock */ protected static final Object lock = new Object(); /** The class loader used to find the Attach API Jar */ protected static final AtomicReference<ClassLoader> attachClassLoader = new AtomicReference<ClassLoader>(null); /** A cache of the reflectively loaded classes keyed by class name */ protected final Map<String, Class<?>> classCache = new HashMap<String, Class<?>>(); /** The jar file that usually contains the attach API VirtualMachine classes */ public static final String JAR_NAME = "tools.jar"; /** The Java Home location */ public static final String JAVA_HOME = System.getProperty("java.home"); /** Alternate locations to look for tools.jar */ public static final String[] ALT_LOCS = { File.separator + ".." + File.separator + "lib" + File.separator }; /** The attach API VirtualMachine class name */ public static final String VM_CLASS = "com.sun.tools.attach.VirtualMachine"; /** The attach API VirtualMachineDescriptor class name */ public static final String VM_DESC_CLASS = "com.sun.tools.attach.VirtualMachineDescriptor"; /** The attach API AttachProvider class name */ public static final String ATTACH_PROVIDER_CLASS = "com.sun.tools.attach.spi.AttachProvider"; /** * Returns the VirtualMachineBootstrap instance * @return the VirtualMachineBootstrap instance */ public static VirtualMachineBootstrap getInstance() { return getInstance(null); } /** * Returns the VirtualMachineBootstrap instance * @param urlLocation An optional override fully qualified URL of the attach jar * @return the VirtualMachineBootstrap instance */ public static VirtualMachineBootstrap getInstance(String urlLocation) { if(instance==null) { synchronized(lock) { if(instance==null) { instance = new VirtualMachineBootstrap(urlLocation); try { AttachProvider.init(); } catch (Exception e) { e.printStackTrace(System.err); throw new RuntimeException("Failed to load Attach API Class. (If you are running a JRE, you need to use a JDK with a tools.jar", e); } } } } return instance; } /** * Creates a new VirtualMachineBootstrap * @param urlLocation An optional override fully qualified URL of the attach jar */ protected VirtualMachineBootstrap(String urlLocation) { findAttachAPI(urlLocation); ClassLoader cl = attachClassLoader.get(); try { classCache.put(VM_CLASS, Class.forName(VM_CLASS, true, cl)); classCache.put(VM_DESC_CLASS, Class.forName(VM_DESC_CLASS, true, cl)); classCache.put(ATTACH_PROVIDER_CLASS, Class.forName(ATTACH_PROVIDER_CLASS, true, cl)); BaseWrappedClass.getMethodMapping(classCache.get(VM_CLASS)); BaseWrappedClass.getMethodMapping(classCache.get(VM_DESC_CLASS)); BaseWrappedClass.getMethodMapping(classCache.get(ATTACH_PROVIDER_CLASS)); } catch (Exception e) { e.printStackTrace(System.err); throw new RuntimeException("Failed to load Attach API Class. (If you are running a JRE, you need to use a JDK with a tools.jar", e); } } /** * Determines if the passed delegate object is an Attach API class instance and if it is an instance of the named class. * @param obj The delegate object to pass * @param className The class name to test as * @return true if the object is of the passed class. */ public boolean isInstanceOf(Object obj, String className) { if(obj==null) throw new IllegalArgumentException("The passed delegate object was null", new Throwable()); if(className==null) throw new IllegalArgumentException("The passed class name was null", new Throwable()); Class<?> clazz = classCache.get(className); if(clazz==null) throw new IllegalArgumentException("The passed class name [" + className + "] is not an Attach API class", new Throwable()); return clazz.isAssignableFrom(obj.getClass()); } /** * Indicates if the Attach VirtualMachine class can be found in the current classpath * @return true if the Attach VirtualMachine class can be loaded, false if it cannot. */ protected static boolean inClassPath() { return inClassPath(Thread.currentThread().getContextClassLoader()); } /** * Indicates if the Attach VirtualMachine class can be found in the current classpath * @param classLoader The class loader used to find the Attach API Jar * @return true if the Attach VirtualMachine class can be loaded, false if it cannot. */ protected static boolean inClassPath(ClassLoader classLoader) { if(attachClassLoader.get()!=null) return true; try { Class<?> clazz = Class.forName(VM_CLASS, true, classLoader); attachClassLoader.set(clazz.getClassLoader()==null ? classLoader : clazz.getClassLoader()); return true; } catch (Exception e) { return false; } } /** * Searches for the Attach API jar */ protected static void findAttachAPI() { findAttachAPI(null); } /** * Searches for the Attach API jar * @param urlLocation An optional override fully qualified URL of the attach jar */ protected static void findAttachAPI(String urlLocation) { //if(inClassPath()) return; try { Class<?> clazz = Class.forName(VM_CLASS); log("Found AttachAPI in Standard ClassPath [" + clazz.getClassLoader() + "]"); ClassLoader cl = clazz.getClassLoader(); if(cl==null) { cl = ClassLoader.getSystemClassLoader(); } log("Attach API ClassLoader:" + cl); attachClassLoader.set(cl); BaseWrappedClass.savedState.set(null); return; } catch (Exception e) {} List<String> altLocs = new ArrayList<String>(); if(urlLocation!=null) { altLocs.add(urlLocation); } for(String s: ALT_LOCS) { altLocs.add(JAVA_HOME + s + JAR_NAME); } for(String s: altLocs) { try { File toolsLoc = new File(s); //log("Testing [" + toolsLoc + "]"); if(toolsLoc.exists()) { URL url = toolsLoc.toURI().toURL(); URLClassLoader ucl = new URLClassLoader(new URL[]{url}, ClassLoader.getSystemClassLoader().getParent()); if(inClassPath(ucl)) { //log("Attach API Found And Loaded [" + toolsLoc + "]"); // attachClassLoader.set(ucl); // BaseWrappedClass.savedState.set(null); return; } } } catch (Exception e) { } } if(attachClassLoader.get()==null) { throw new RuntimeException("Failed to find the Atach API. Please add tools.jar to the classpath", new Throwable()); } } public static void main(String[] args) { findAttachAPI(); log("VMBoot:" + inClassPath()); VirtualMachineBootstrap vmb = getInstance(); // for(VirtualMachineDescriptor vmd: VirtualMachine.list()) { // try { // VirtualMachine vm = VirtualMachine.attach(vmd); // log("\tVM:" + vm.toString()); // } catch (Exception e) { // log("Unable to attach to VM [" + vmd.toString() + "]:" + e); // } // } // for(VirtualMachineDescriptor vmd: VirtualMachineDescriptor.getVirtualMachineDescriptors()) { // try { // VirtualMachine vm = VirtualMachine.attach(vmd); // log("\tVM:" + vm.toString()); // } catch (Exception e) { // log("Unable to attach to VM [" + vmd.toString() + "]:" + e); // } // } // AttachProvider ap = AttachProvider.getAttachProviders().iterator().next(); // String id = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; // VirtualMachine vm = ap.attachVirtualMachine(id); // log("This VM:" + vm.toString()); AttachProvider ap = AttachProvider.getAttachProviders().iterator().next(); String id = ManagementFactory.getRuntimeMXBean().getName().split("@")[0]; for(VirtualMachineDescriptor vmd: ap.listVirtualMachines()) { log("Testing VMD (" + vmd.id() + ") [" + vmd.displayName() + "] Name:" + vmd.provider().name() + " Type:" + vmd.provider().type()); if(id.equals(vmd.id())) { VirtualMachine vm = ap.attachVirtualMachine(vmd); log("This VM:" + vm.toString()); Properties agentProps = vm.getAgentProperties(); for(Map.Entry<Object, Object> p: agentProps.entrySet()) { log("\t\t" + p.getKey() + ":" + p.getValue()); } } if(vmd.id().equals("15684")) { // log("============== System Props =============="); // Properties sysProps = ap.attachVirtualMachine(vmd).getSystemProperties(); // for(Map.Entry<Object, Object> p: sysProps.entrySet()) { // log("\t\t" + p.getKey() + ":" + p.getValue()); // } log("============== Agent Props =============="); Properties agentProps = ap.attachVirtualMachine(vmd).getAgentProperties(); for(Map.Entry<Object, Object> p: agentProps.entrySet()) { log("\t\t" + p.getKey() + ":" + p.getValue()); } } } // BaseWrappedClass.getMethodMapping(vmb.classCache.get(VM_CLASS)); // for(VirtualMachineDescriptor vmd: VirtualMachine.list()) { // log(vmd.toString()); // } } public static void log(Object msg) { System.out.println(msg); } }